package com.example.keepserver.service.impl;

import com.example.keepserver.dto.ActivityDTO;
import com.example.keepserver.dto.PlatformStatsDTO;
import com.example.keepserver.dto.UserTypeDistributionDTO;
import com.example.keepserver.model.Activity;
import com.example.keepserver.model.User;
import com.example.keepserver.repository.ActivityRepository;
import com.example.keepserver.repository.UserRepository;
import com.example.keepserver.service.ActivityService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class ActivityServiceImpl implements ActivityService {

    private final ActivityRepository activityRepository;
    private final UserRepository userRepository;

    @Autowired
    public ActivityServiceImpl(ActivityRepository activityRepository, UserRepository userRepository) {
        this.activityRepository = activityRepository;
        this.userRepository = userRepository;
    }

    @Override
    public List<ActivityDTO> getActivitiesByUserId(String userId, LocalDateTime startDate, LocalDateTime endDate) {
        Optional<User> userOpt = userRepository.findById(userId);
        if (!userOpt.isPresent()) {
            return Collections.emptyList();
        }
        User user = userOpt.get();
        List<Activity> activities = activityRepository.findByUserAndStartTimeBetween(user, startDate, endDate);
        return activities.stream().map(this::convertToDTO).collect(Collectors.toList());
    }

    @Override
    public List<ActivityDTO> getAllActivities(LocalDateTime startDate, LocalDateTime endDate) {
        List<Activity> activities = activityRepository.findByStartTimeBetween(startDate, endDate);
        return activities.stream().map(this::convertToDTO).collect(Collectors.toList());
    }

    @Override
    public Map<String, Object> getActivityStatsByUser(String userId, LocalDateTime startDate, LocalDateTime endDate) {
        Map<String, Object> result = new HashMap<>();
        
        Optional<User> userOpt = userRepository.findById(userId);
        if (!userOpt.isPresent()) {
            return result;
        }
        
        User user = userOpt.get();
        List<Activity> activities = activityRepository.findByUserAndStartTimeBetween(user, startDate, endDate);
        
        // 按类型分组统计
        Map<String, List<Activity>> activitiesByType = activities.stream()
                .collect(Collectors.groupingBy(Activity::getType));
        
        Map<String, Map<String, Object>> statsByType = new HashMap<>();
        activitiesByType.forEach((type, typeActivities) -> {
            Map<String, Object> typeStats = new HashMap<>();
            
            int count = typeActivities.size();
            double totalDistance = typeActivities.stream().mapToDouble(a -> a.getDistance() != null ? a.getDistance() : 0).sum();
            int totalDuration = typeActivities.stream().mapToInt(a -> a.getDuration() != null ? a.getDuration() : 0).sum();
            double totalCalorie = typeActivities.stream().mapToDouble(a -> a.getCalorie() != null ? a.getCalorie() : 0).sum();
            
            // 计算平均心率（假设通过某种方式获取心率数据）
            double avgHeartRate = 145.0; // 模拟数据
            double maxHeartRate = 180.0; // 模拟数据
            
            typeStats.put("count", count);
            typeStats.put("totalDistance", totalDistance);
            typeStats.put("totalDuration", totalDuration);
            typeStats.put("totalCalorie", totalCalorie);
            typeStats.put("avgHeartRate", avgHeartRate);
            typeStats.put("maxHeartRate", maxHeartRate);
            
            statsByType.put(type, typeStats);
        });
        
        result.putAll(statsByType);
        return result;
    }

    @Override
    public Map<String, Object> getActivityTimeTrend(String userId, LocalDateTime startDate, LocalDateTime endDate) {
        Map<String, Object> result = new HashMap<>();
        
        List<Activity> activities;
        if (userId != null && !userId.isEmpty()) {
            Optional<User> userOpt = userRepository.findById(userId);
            if (!userOpt.isPresent()) {
                return result;
            }
            User user = userOpt.get();
            activities = activityRepository.findByUserAndStartTimeBetween(user, startDate, endDate);
        } else {
            activities = activityRepository.findByStartTimeBetween(startDate, endDate);
        }
        
        // 按日期分组
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        Map<String, List<Activity>> activitiesByDate = activities.stream()
                .collect(Collectors.groupingBy(a -> a.getStartTime().format(formatter)));
        
        // 计算每天的总数据
        Map<String, Map<String, Object>> dailyStats = new TreeMap<>();
        activitiesByDate.forEach((date, dateActivities) -> {
            Map<String, Object> stats = new HashMap<>();
            
            double totalDistance = dateActivities.stream().mapToDouble(a -> a.getDistance() != null ? a.getDistance() : 0).sum();
            int totalDuration = dateActivities.stream().mapToInt(a -> a.getDuration() != null ? a.getDuration() : 0).sum();
            double totalCalorie = dateActivities.stream().mapToDouble(a -> a.getCalorie() != null ? a.getCalorie() : 0).sum();
            
            stats.put("totalDistance", totalDistance);
            stats.put("totalDuration", totalDuration);
            stats.put("totalCalorie", totalCalorie);
            stats.put("activities", dateActivities.size());
            
            dailyStats.put(date, stats);
        });
        
        // 提取日期顺序列表和各项数据列表
        List<String> dates = new ArrayList<>(dailyStats.keySet());
        List<Double> distance = dates.stream().map(date -> (Double) dailyStats.get(date).get("totalDistance")).collect(Collectors.toList());
        List<Integer> duration = dates.stream().map(date -> (Integer) dailyStats.get(date).get("totalDuration")).collect(Collectors.toList());
        List<Double> calorie = dates.stream().map(date -> (Double) dailyStats.get(date).get("totalCalorie")).collect(Collectors.toList());
        
        result.put("dates", dates);
        result.put("distance", distance);
        result.put("duration", duration);
        result.put("calorie", calorie);
        
        return result;
    }

    @Override
    public Map<String, Object> getTrainingIntensity(String userId, LocalDateTime startDate, LocalDateTime endDate) {
        Map<String, Object> result = new HashMap<>();
        
        List<Activity> activities;
        if (userId != null && !userId.isEmpty()) {
            Optional<User> userOpt = userRepository.findById(userId);
            if (!userOpt.isPresent()) {
                return result;
            }
            User user = userOpt.get();
            activities = activityRepository.findByUserAndStartTimeBetween(user, startDate, endDate);
        } else {
            activities = activityRepository.findByStartTimeBetween(startDate, endDate);
        }
        
        // 定义心率区间
        Map<String, Integer> zones = new LinkedHashMap<>();
        zones.put("恢复区 (< 120)", 0);
        zones.put("有氧区 (120-140)", 0);
        zones.put("耐力区 (140-160)", 0);
        zones.put("无氧区 (160-180)", 0);
        zones.put("极限区 (> 180)", 0);
        
        // 模拟心率数据分析
        Random random = new Random();
        for (Activity activity : activities) {
            // 这里是模拟数据，实际应该从活动记录中提取心率数据
            int heartRate = 120 + random.nextInt(70); // 模拟心率在120-190之间
            
            if (heartRate < 120) {
                zones.put("恢复区 (< 120)", zones.get("恢复区 (< 120)") + 1);
            } else if (heartRate <= 140) {
                zones.put("有氧区 (120-140)", zones.get("有氧区 (120-140)") + 1);
            } else if (heartRate <= 160) {
                zones.put("耐力区 (140-160)", zones.get("耐力区 (140-160)") + 1);
            } else if (heartRate <= 180) {
                zones.put("无氧区 (160-180)", zones.get("无氧区 (160-180)") + 1);
            } else {
                zones.put("极限区 (> 180)", zones.get("极限区 (> 180)") + 1);
            }
        }
        
        // 返回结果
        result.putAll(zones);
        return result;
    }

    @Override
    public Map<String, Object> getActivityLocations(String userId, LocalDateTime startDate, LocalDateTime endDate) {
        Map<String, Object> locationStats = new HashMap<>();
        
        List<Activity> activities;
        if (userId != null && !userId.isEmpty()) {
            Optional<User> userOpt = userRepository.findById(userId);
            if (!userOpt.isPresent()) {
                return locationStats;
            }
            User user = userOpt.get();
            activities = activityRepository.findByUserAndStartTimeBetween(user, startDate, endDate);
        } else {
            activities = activityRepository.findByStartTimeBetween(startDate, endDate);
        }
        Map<String, String> locationMap = new HashMap<>();
        locationMap.put("activity001", "城市公园");
        locationMap.put("activity002", "城市街道");
        locationMap.put("activity003", "郊外公路");
        locationMap.put("activity004", "游泳馆");
        locationMap.put("activity005", "城市公园");
        locationMap.put("activity006", "山地公路");
        locationMap.put("activity007", "城市街道");
        locationMap.put("activity008", "健身房");
        locationMap.put("activity009", "瑜伽馆");
        locationMap.put("activity010", "公园跑道");
        // 按位置统计
        Map<String, Map<String, Object>> stats = new HashMap<>();
        for (Activity activity : activities) {
            String location = locationMap.getOrDefault(activity.getActivityId(), "未知");
            if (!stats.containsKey(location)) {
                Map<String, Object> locStats = new HashMap<>();
                locStats.put("count", 0);
                locStats.put("totalDistance", 0.0);
                locStats.put("totalDuration", 0);
                locStats.put("totalCalorie", 0.0);
                stats.put(location, locStats);
            }
            Map<String, Object> locStats = stats.get(location);
            locStats.put("count", (Integer) locStats.get("count") + 1);
            locStats.put("totalDistance", (Double) locStats.get("totalDistance") + (activity.getDistance() != null ? activity.getDistance() : 0));
            locStats.put("totalDuration", (Integer) locStats.get("totalDuration") + (activity.getDuration() != null ? activity.getDuration() : 0));
            locStats.put("totalCalorie", (Double) locStats.get("totalCalorie") + (activity.getCalorie() != null ? activity.getCalorie() : 0));
        }
        locationStats.putAll(stats);
        return locationStats;
    }

    @Override
    public List<UserTypeDistributionDTO> getUserTypeDistribution(LocalDateTime startDate, LocalDateTime endDate) {
        List<Map<String, Object>> userTypeData = activityRepository.countActivitiesByUserAndType(startDate, endDate);
        // 按用户ID分组
        Map<String, Map<String, Integer>> userTypeMap = new HashMap<>();
        for (Map<String, Object> data : userTypeData) {
            String userId = (String) data.get("userId");
            String type = (String) data.get("type");
            Long count = ((Number) data.get("count")).longValue();
            if (!userTypeMap.containsKey(userId)) {
                userTypeMap.put(userId, new HashMap<>());
            }
            userTypeMap.get(userId).put(type, count.intValue());
        }
        // 构建DTO
        List<UserTypeDistributionDTO> result = new ArrayList<>();
        for (Map.Entry<String, Map<String, Integer>> entry : userTypeMap.entrySet()) {
            String userId = entry.getKey();
            Map<String, Integer> typeDistribution = entry.getValue();
            Optional<User> userOpt = userRepository.findById(userId);
            if (!userOpt.isPresent()) {
                continue;
            }
            User user = userOpt.get();
            UserTypeDistributionDTO dto = new UserTypeDistributionDTO();
            dto.setUserId(userId);
            dto.setNickname(user.getNickname());
            dto.setTotalActivities(typeDistribution.values().stream().mapToInt(Integer::intValue).sum());
            dto.setTypeDistribution(typeDistribution);
            result.add(dto);
        }
        // 按总活动数排序
        result.sort((a, b) -> b.getTotalActivities() - a.getTotalActivities());
        return result;
    }

    @Override
    public PlatformStatsDTO getPlatformStats(LocalDateTime startDate, LocalDateTime endDate) {
        PlatformStatsDTO dto = new PlatformStatsDTO();
        // 1. 获取总体统计数据
        List<Activity> activities = activityRepository.findByStartTimeBetween(startDate, endDate);
        long totalActivities = activities.size();
        double totalDistance = activities.stream().mapToDouble(a -> a.getDistance() != null ? a.getDistance() : 0).sum();
        int totalDuration = activities.stream().mapToInt(a -> a.getDuration() != null ? a.getDuration() : 0).sum();
        double totalCalorie = activities.stream().mapToDouble(a -> a.getCalorie() != null ? a.getCalorie() : 0).sum();
        int uniqueUsers = activityRepository.countUniqueUsers(startDate, endDate);
        PlatformStatsDTO.SummaryDTO summary = new PlatformStatsDTO.SummaryDTO();
        summary.setTotalActivities(totalActivities);
        summary.setTotalDistance(new BigDecimal(totalDistance).setScale(1, RoundingMode.HALF_UP).doubleValue());
        summary.setTotalDuration(totalDuration / 60); // 转为分钟
        summary.setTotalCalorie((int) totalCalorie);
        summary.setUniqueUsers(uniqueUsers);
        dto.setSummary(summary);
        // 2. 获取按日期分组的统计数据
        List<Map<String, Object>> dailyStatsData = activityRepository.getStatsByDate(startDate, endDate);
        Map<String, PlatformStatsDTO.DailyStatsDTO> dailyStats = new HashMap<>();
        for (Map<String, Object> data : dailyStatsData) {
            String date = (String) data.get("date");
            long count = ((Number) data.get("count")).longValue();
            double distanceSum = data.get("totalDistance") != null ? ((Number) data.get("totalDistance")).doubleValue() : 0;
            int durationSum = data.get("totalDuration") != null ? ((Number) data.get("totalDuration")).intValue() : 0;
            double calorieSum = data.get("totalCalorie") != null ? ((Number) data.get("totalCalorie")).doubleValue() : 0;
            PlatformStatsDTO.DailyStatsDTO dailyStat = new PlatformStatsDTO.DailyStatsDTO();
            dailyStat.setCount((int) count);
            dailyStat.setTotalDistance(new BigDecimal(distanceSum).setScale(1, RoundingMode.HALF_UP).doubleValue());
            dailyStat.setTotalDuration(durationSum / 60); // 转为分钟
            dailyStat.setTotalCalorie((int) calorieSum);
            // 获取每天的唯一用户数
            Set<String> uniqueUserIds = activities.stream()
                    .filter(a -> a.getStartTime().toLocalDate().toString().equals(date))
                    .map(a -> a.getUser().getUserId())
                    .collect(Collectors.toSet());
            dailyStat.setUniqueUserCount(uniqueUserIds.size());
            dailyStats.put(date, dailyStat);
        }
        dto.setDailyStats(dailyStats);
        // 3. 获取每日活跃用户数
        List<Map<String, Object>> activeUsersData = activityRepository.countActiveUsersByDate(startDate, endDate);
        List<PlatformStatsDTO.ActiveUsersDTO> activeUsersByDate = new ArrayList<>();
        for (Map<String, Object> data : activeUsersData) {
            String date = (String) data.get("date");
            long activeUsers = ((Number) data.get("activeUsers")).longValue();
            PlatformStatsDTO.ActiveUsersDTO activeUsersDTO = new PlatformStatsDTO.ActiveUsersDTO();
            activeUsersDTO.setDate(date);
            activeUsersDTO.setActiveUsers((int) activeUsers);
            activeUsersByDate.add(activeUsersDTO);
        }
        dto.setActiveUsersByDate(activeUsersByDate);
        // 4. 获取活动类型分布
        List<Map<String, Object>> typeData = activityRepository.countActivitiesByType(startDate, endDate);
        List<PlatformStatsDTO.TypeDistributionDTO> typeDistribution = new ArrayList<>();
        for (Map<String, Object> data : typeData) {
            String type = (String) data.get("type");
            long count = ((Number) data.get("count")).longValue();
            PlatformStatsDTO.TypeDistributionDTO typeDTO = new PlatformStatsDTO.TypeDistributionDTO();
            typeDTO.setType(type);
            typeDTO.setCount((int) count);
            // 计算百分比
            double percentage = (double) count / totalActivities * 100;
            typeDTO.setPercentage(new BigDecimal(percentage).setScale(1, RoundingMode.HALF_UP).toString());
            typeDistribution.add(typeDTO);
        }
        dto.setTypeDistribution(typeDistribution);
        return dto;
    }

    private ActivityDTO convertToDTO(Activity activity) {
        ActivityDTO dto = new ActivityDTO();
        BeanUtils.copyProperties(activity, dto);
        if (activity.getUser() != null) {
            dto.setUserId(activity.getUser().getUserId());
            dto.setUserNickname(activity.getUser().getNickname());
        }
        return dto;
    }
}